package com.malou.client.seguridad.menu;

import java.util.ArrayList;
import java.util.List;

import com.extjs.gxt.ui.client.Style.HorizontalAlignment;
import com.extjs.gxt.ui.client.Style.LayoutRegion;
import com.extjs.gxt.ui.client.Style.Scroll;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.data.ModelIconProvider;
import com.extjs.gxt.ui.client.event.BaseEvent;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.MenuEvent;
import com.extjs.gxt.ui.client.event.MessageBoxEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.event.TreePanelEvent;
import com.extjs.gxt.ui.client.store.TreeStore;
import com.extjs.gxt.ui.client.util.IconHelper;
import com.extjs.gxt.ui.client.util.Margins;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.Dialog;
import com.extjs.gxt.ui.client.widget.MessageBox;
import com.extjs.gxt.ui.client.widget.VerticalPanel;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.layout.BorderLayout;
import com.extjs.gxt.ui.client.widget.layout.BorderLayoutData;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.extjs.gxt.ui.client.widget.menu.Menu;
import com.extjs.gxt.ui.client.widget.menu.MenuItem;
import com.extjs.gxt.ui.client.widget.treepanel.TreePanel;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.ui.AbstractImagePrototype;
import com.malou.client.MalouConstants;
import com.malou.client.MalouMessages;
import com.malou.client.seguridad.usuario.UsuarioPanel;

public class MenuPanel extends ContentPanel {
	
	private MalouConstants constants = GWT.create(MalouConstants.class);
	private MalouMessages messages = GWT.create(MalouMessages.class);
	public TreePanel<MenuOpciones> tree;
	private MenuDialog dialog;
	private MenuOpciones selectedModel;
	public VerticalPanel vp;
	public Button guardarPermiso;
	
	public boolean fireBehavior;

	public MenuPanel(){
		vp = new VerticalPanel();
		Menus.menuPanel = this;
		//Menus.list();
		Menus.getMenusArray();
	    
	    setBodyBorder(false);  
	      
	    setButtonAlign(HorizontalAlignment.CENTER);  
	    //setLayout(new FitLayout());
	    setLayout(new BorderLayout());
	    setFrame(true);
	    setCollapsible(true);
	    //setSize(600, 300);
		
	    Menus.store = new TreeStore<MenuOpciones>();
	   
		tree = new TreePanel<MenuOpciones>(Menus.store);  
	    
	    tree.setDisplayProperty("menu"); 
	    tree.setWidth(200);
	    //tree.setStateful(true);
	    
	    /*
	    MenuOpciones mnu = new MenuOpciones(200,"Prueba","prueba",1,1,false);
	    mnu.add(new MenuOpciones(200,"Prueba","prueba",2,2,false));
	    Menus.store.add(mnu, true);
	    */
	    tree.setIconProvider(new ModelIconProvider<MenuOpciones>() {
	      public AbstractImagePrototype getIcon(MenuOpciones model) {
	    	  
	    	  Boolean hasChildren = model.getHaschildren();
	    	  Integer tipo = model.getTipo();
	    	  String parametro = model.getParametro();
	    	  
	    	  if(tipo == 1){
	    		  //es un programa
	    		  if (hasChildren != null){
	    			  //si tiene hijos
	    			  if(parametro.equals("") || parametro == null)
	    				  return null;
	    			  else
	    				  return IconHelper.createPath("images/icons/table.png");
	    		  }
	    		  else
	    			  return IconHelper.createPath("images/icons/table.png");
	    	  }
	    	  else{
	    		  // es una operacion
	    		  return IconHelper.createPath("images/icons/tool.png");
	    	  }
	    	        
	      }
	    });
	    
	    dialog = new MenuDialog();        
		dialog.menuPanel = this;
		dialog.setStore(Menus.store);
	    
	    Menu contextMenu = new Menu();

	    MenuItem insert = new MenuItem();  
	    insert.setText(constants.menuAgregarMenu());
	    insert.setId("insert");
	    insert.setIcon(IconHelper.createStyle("icon-new"));  
	    insert.addSelectionListener(new SelectionListener<MenuEvent>() {  
	      public void componentSelected(MenuEvent ce) {
	    	  MenuOpciones selectedModel = tree.getSelectionModel().getSelectedItem();
	    	  dialog.beforeAddMenu();
	    	  dialog.reset();
	    	  dialog.unbind();
	    	  dialog.parent_id.setValue(selectedModel.getId().toString());
	    	  dialog.tipo.setValue("1"); //tipo 1: menu, tipo 2: operacion
	    	  dialog.show();	    	 
	      }  
	    });  
	    contextMenu.add(insert);
	    
	    MenuItem tool = new MenuItem();  
	    tool.setText(constants.menuAgregarOperacion());
	    tool.setId("tool");
	    tool.setIcon(IconHelper.createStyle("icon-tool"));  
	    tool.addSelectionListener(new SelectionListener<MenuEvent>() {  
	      public void componentSelected(MenuEvent ce) {
	    	  MenuOpciones selectedModel = tree.getSelectionModel().getSelectedItem();
	    	  dialog.beforeAddTool();
	    	  dialog.reset();
	    	  dialog.unbind();
	    	  dialog.parent_id.setValue(selectedModel.getId().toString());
	    	  dialog.tipo.setValue("2"); //tipo 1: menu, tipo 2: operacion
	    	  dialog.show();	    	 
	      }  
	    });  
	    contextMenu.add(tool);
	    
	    MenuItem edit = new MenuItem();  
	    edit.setText(constants.editar());
	    edit.setId("edit");
	    edit.setIcon(IconHelper.createStyle("icon-update"));  
	    edit.addSelectionListener(new SelectionListener<MenuEvent>() {  
	      public void componentSelected(MenuEvent ce) {
	    	  MenuOpciones selectedModel = tree.getSelectionModel().getSelectedItem();
	    	  if(selectedModel.getParametro().equals("") && selectedModel.getHaschildren() != null)
	    		  dialog.parametro.setEnabled(false);
	    	  else
	    		  dialog.parametro.setEnabled(true);
	    	  dialog.bind(selectedModel);
	    	  if(selectedModel.getTipo()==1)
	    		  dialog.beforeEditMenu();
	    	  else if(selectedModel.getTipo()==2)
	    		  dialog.beforeEditTool();  
	    	  dialog.show();
	      }  
	    });
	    
	    contextMenu.add(edit);
	    
	    final Listener<MessageBoxEvent> l = new Listener<MessageBoxEvent>() {  
	          public void handleEvent(MessageBoxEvent ce) {  
	            String button_id = ce.getButtonClicked().getItemId();  
	             if(Dialog.YES == button_id){	        		 
	            	 if(selectedModel != null){
	            		 Integer id = selectedModel.get("id");            		 
	            		 Menus.delete(id);
	            	 }
	            }
	         }  
	    };
	  
	    MenuItem remove = new MenuItem();  
	    remove.setText(constants.eliminar());
	    remove.setId("remove");
	    remove.setIcon(IconHelper.createStyle("icon-delete"));  
	    remove.addSelectionListener(new SelectionListener<MenuEvent>() {  
	      public void componentSelected(MenuEvent ce) {
	    	  selectedModel = tree.getSelectionModel().getSelectedItem();
	    	  String mensaje="";
	    	  if(selectedModel.getTipo()==1)
	    		  mensaje = messages.menuEstaSeguro(selectedModel.getMenu());
	    	  else if(selectedModel.getTipo()==2)
	    		  mensaje = messages.menuEstaSeguroOperacion(selectedModel.getMenu());
	    	  
	    	  MessageBox.confirm(constants.confirmacion(), mensaje, l).getDialog().getButtonById(Dialog.YES).setText(constants.si());	    	  
	      }  
	    });
	    
	    contextMenu.add(remove);	     
	    
	    MenuItem reload = new MenuItem();  
	    reload.setText(constants.actualizar());
	    reload.setId("reload");
	    reload.setIcon(IconHelper.createStyle("x-tbar-refresh"));  
	    reload.addSelectionListener(new SelectionListener<MenuEvent>() {  
	      public void componentSelected(MenuEvent ce) {
	    	  //Menus.loader.load();
	    	  Menus.getMenusArray();
	      }  
	    });  
	    contextMenu.add(reload); 
	  
	    tree.setContextMenu(contextMenu);
	    tree.setCheckable(false);    
	    
	    
	    //Para agregar menus Raiz
	    Menu contextMenuRaiz = new Menu();
	    
	    insert = new MenuItem();  
	    insert.setText(constants.menuAgregarMenu());  
	    insert.setIcon(IconHelper.createStyle("icon-new"));  
	    insert.addSelectionListener(new SelectionListener<MenuEvent>() {  
	      public void componentSelected(MenuEvent ce) {
	    	  dialog.beforeAddMenu();
	    	  dialog.reset();
	    	  dialog.unbind();
	    	  dialog.tipo.setValue("1"); //tipo 1: menu, tipo 2: operacion
	    	  dialog.show();	    	 
	      }  
	    });  
	    contextMenuRaiz.add(insert);
	    
	    reload = new MenuItem();  
	    reload.setText(constants.actualizar());  
	    reload.setIcon(IconHelper.createStyle("x-tbar-refresh"));  
	    reload.addSelectionListener(new SelectionListener<MenuEvent>() {  
	      public void componentSelected(MenuEvent ce) {
	    	  //Menus.loader.load();
	    	  Menus.getMenusArray();
	      }  
	    });  
	    contextMenuRaiz.add(reload); 
	 
	    
	    
		setIcon(IconHelper.createPath("images/icons/table.png"));  
        setHeading(constants.menuListaMenus());  
        //this.setLayout(new FitLayout());
        
                
        setButtonAlign(HorizontalAlignment.RIGHT);
        guardarPermiso = new Button("Guardar Permisos", IconHelper.createPath("images/icons/save_all.png"));
        guardarPermiso.setEnabled(false);
        addButton(guardarPermiso);
        
        guardarPermiso.addSelectionListener(new SelectionListener<ButtonEvent>() {
			
			@Override
			public void componentSelected(ButtonEvent ce) {
				guardarPermiso.setEnabled(false);
				List<Integer> updateToPermited = getAllChecked(false);
				List<Integer> insertToPermited = getAllChecked(null);
				List<Integer> updateIfExistElseInsertToNoPermited = getAllUnchecked();
				Menus.savePermisos(updateToPermited, insertToPermited, updateIfExistElseInsertToNoPermited);				
			}
		});
        
        vp.setContextMenu(contextMenuRaiz);
        vp.addListener(Events.OnContextMenu, new Listener<BaseEvent>(){

			@Override
			public void handleEvent(BaseEvent be) {
				tree.getSelectionModel().deselectAll();				
			}	
        	
        });
        vp.setLayout(new FitLayout());
        vp.addStyleName("fondo-blanco");
        vp.setBorders(true);
        vp.setScrollMode(Scroll.AUTOY);
        
        tree.addListener(Events.OnContextMenu, new Listener<TreePanelEvent<MenuOpciones>>(){

			@Override
			public void handleEvent(TreePanelEvent<MenuOpciones> be) {
				MenuOpciones item = be.getItem();
				MenuItem mnu_insert = (MenuItem)tree.getContextMenu().getItemByItemId("insert");
				MenuItem mnu_tool = (MenuItem)tree.getContextMenu().getItemByItemId("tool");
				
				if(!item.getParametro().equals("") && item.getHaschildren()!= null){
					mnu_insert.setEnabled(false);
					mnu_tool.setEnabled(true);
				}
				else if(item.getParametro().equals("") && item.getHaschildren()!= null){
					mnu_tool.setEnabled(false);
					mnu_insert.setEnabled(true);
				}
				else if(item.getTipo() == 2){//tipo 2: operacion; tipo 1: programa
					mnu_insert.setEnabled(false);
					mnu_tool.setEnabled(false);
				}					
				else{
					mnu_insert.setEnabled(true);
					mnu_tool.setEnabled(true);
				}
				
			}
        	
        });    
        
        vp.add(tree);
        
        tree.addListener(Events.OnClick,new Listener<TreePanelEvent<MenuOpciones>>(){

			@Override
			public void handleEvent(TreePanelEvent<MenuOpciones> be) {
				if(tree.isCheckable())
				fireBehavior = true;				
			}
        	
        });
        tree.addListener(Events.CheckChange, new Listener<TreePanelEvent<MenuOpciones>>(){

			@Override
			public void handleEvent(TreePanelEvent<MenuOpciones> be) {
				
				if(fireBehavior){
					fireBehavior = false;
					MenuOpciones m = be.getItem();
					
					if(be.isChecked()){						
						checkChildren(m);						
						checkParent(m);
					}else{						
						uncheckChildren(m);
						uncheckParent(m);						
					}					
				}				
			}        	
        });        
        
        UsuarioPanel up = new UsuarioPanel();
        up.menuPanel = this;
        
        BorderLayoutData centerData = new BorderLayoutData(LayoutRegion.CENTER);  
        centerData.setMargins(new Margins(0));
        
        BorderLayoutData eastData = new BorderLayoutData(LayoutRegion.EAST, 250);  
        eastData.setSplit(true);  
        eastData.setCollapsible(true);  
        eastData.setMargins(new Margins(0,0,0,5));
        add(up, centerData);
        
        add(vp, eastData);
	}
	
	private void checkParent(MenuOpciones m){
		MenuOpciones parent = (MenuOpciones)m.getParent();
		if(parent != null){
			if(!tree.isChecked(parent)){
				tree.setChecked(parent, true);				
				checkParent(parent);
			}
		}
	}		
	
	private void checkChildren(MenuOpciones m){
		for(ModelData d: m.getChildren()){
			MenuOpciones md = (MenuOpciones)d;
			tree.setChecked(md, true);			
			checkChildren(md);
		}
	}
	
	private void uncheckChildren(MenuOpciones m){
		for(ModelData d: m.getChildren()){
			MenuOpciones md = (MenuOpciones)d;
			tree.setChecked(md, false);			
			uncheckChildren(md);
		}
	}
	
	private void uncheckParent(MenuOpciones m){
		if(m.getParent() != null){
			MenuOpciones parent = (MenuOpciones)m.getParent();
			Boolean uncheck = true;
			if(parent.getHaschildren() != null)
			for(ModelData d: parent.getChildren()){
				MenuOpciones md = (MenuOpciones)d;
				if(tree.isChecked(md)){
					uncheck = false;
					break;
				}
			}
			if(uncheck){
				tree.setChecked(parent, false);
				uncheckParent(parent);
			}
		}
	}
	
	public void checkPermitidos(){
		for(MenuOpciones mn : Menus.store.getAllItems()){			
			if(mn.getPermitido() != null){
				if(mn.getPermitido())
					tree.setChecked(mn, true);
			}
		}
	}
	
	public List<Integer> getAllUnchecked(){
		List<Integer> ids = new ArrayList<Integer>();
		for(MenuOpciones mn : Menus.store.getAllItems()){
			if(mn.getPermitido() != null)
			if(mn.getPermitido() && !tree.isChecked(mn)){
				ids.add(mn.getId());
			}			
		}
		return ids;
	}
	
	public List<Integer> getAllChecked(Boolean permitido){
		List<Integer> ids = new ArrayList<Integer>();
		for(MenuOpciones mn : tree.getCheckedSelection()){
			if(permitido == null){
				if(mn.getPermitido() == null){
					ids.add(mn.getId());
				}	
			}else if(!permitido){
				if(mn.getPermitido() != null)
				if(!mn.getPermitido()){
					ids.add(mn.getId());
				}
			}			
		}
		return ids;
	}
	
}
